// 
// OV-chip 2.0 project
// 
// Digital Security (DS) group at Radboud Universiteit Nijmegen
// 
// Copyright (C) 2008, 2009
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License in file COPYING in this or one of the
// parent directories for more details.
// 
// Created 25.8.08 by Hendrik
// 
// interface for object to be sent or received
// 
// $Id: APDU_Serializable.java,v 1.12 2009-05-28 15:17:03 tews Exp $

#include <config>

#ifdef PACKAGE
  package PACKAGE;
#else
  package ds.ov2.util;
#endif

// <A HREF="../util/APDU_Serializable.html#apdu_compatibility"></A>

/** 
 * Interface for data types that can be sent to the card by the
 * OV-chip protocol layer. The OV-chip protocol layer is a OV-chip protocol
 * layer that overcomes the one-APDU restriction of Java Card RMI. In
 * addition it can enforce that certain methods are always called in a
 * certain order. Arguments and results (yes, the OV-chip protocol layer
 * fixes the ridiculous one-result-limitation of Java and permits
 * methods to return multiple results) of these methods must implement
 * the APDU_Serializable interface. <P>
 *
 * <a name="serialization">
 * <H4>Serialization</H4>
 *
 * In the process of sending and receiving objects to and from the 
 * card the internal state of those objects is converted to and from
 * a byte array with the methods {@link #to_byte_array to_byte_array}
 * and {@link #from_byte_array from_byte_array}, respectively. The 
 * conversion into a byte array is called <EM>serialization</EM>.
 * The reverse is sometimes called <EM>deserialization</EM>.
 * <P>
 *
 * APDU's, which are used as transport medium, are limited to 255 
 * bytes of data. Therefore (de-)serialization can happen in serval pieces.
 * This applies equally well to short data types, because they might be 
 * so unlucky to lay precisely on an APDU boundary (because, for instance,
 * the preceeding argument used just 254 bytes).
 *
 *
 * <a name="apdu_compatibility">
 * <H4>Compatibility Checks</H4>
 *
 * In principle the arguments and expected results on the 
 * host side must be identical in type and size to those on the card. 
 * However, whether this type equality holds is determined by
 * {@link #is_compatible_with is_compatible_with} at runtime, and careful
 * cheating is permitted here. For instance, arguments of type 
 * {@link ds.ov2.bignat.Bignat Bignat}
 * on the card are usually represented by 
 * {@link ds.ov2.bignat.APDU_BigInteger APDU_BigInteger} 
 * on the host. With this trick
 * the OV-chip protocol layer performs convenient data-type conversions 
 * almost for free.
 * <P>
 *
 * The method {@link #is_compatible_with is_compatible_with} is only
 * called on those objects that are declared as arguments or results
 * in the relevant {@link Protocol} descriptions on the host. 
 * It is not called on
 * the arguments that the host code actually supplies. 
 * And it is never called on the card.
 * Therefore pure
 * host data types, such as 
 * {@link ds.ov2.bignat.APDU_BigInteger APDU_BigInteger} or
 * {@link ds.ov2.bignat.Host_modulus Host_modulus}, do not need to 
 * put anything sensible into the body of {@link #is_compatible_with 
 * is_compatible_with}.
 * The card only checks the size of the byte stream it receives. It does 
 * not perform any further type checks. 
 * <P>
 * 
 * Consider, for
 * an example, a method that takes a {@link ds.ov2.bignat.Bignat Bignat}
 * argument. There will be a Bignat object in the argument array of the 
 * relevant {@link Protocol_step} instance. When the host code calls
 * this method via the OV-chip protocol layer it might supply an
 * {@link ds.ov2.bignat.APDU_BigInteger APDU_BigInteger} object as 
 * argument. The method {@link #is_compatible_with is_compatible_with}
 * is only invoked on the Bignat object with the APDU_BigInteger object as
 * argument. It is not invoked on the APDU_BigInteger object.
 * <P>
 *
 * (The stub code that is generated by the protocol-IDL compiler
 * performs further type conversions. In the example of the last
 * paragraph the host driver would supply an {@link
 * java.math.BigInteger} as argument to the stub method. The stub
 * method will wrap an {@link ds.ov2.bignat.APDU_BigInteger
 * APDU_BigInteger} around it.
 *
 * @author Hendrik Tews
 * @version $Revision: 1.12 $
 * @commitdate $Date: 2009-05-28 15:17:03 $ by $Author: tews $
 * @environment host, card
 * @CPP This class uses the following cpp defines:
 *   <a href="../../../overview-summary.html#PACKAGE">PACKAGE</a>,
 *   <a href="../../../overview-summary.html#PUBLIC">PUBLIC</a>
 *
 */
PUBLIC interface APDU_Serializable {

    /**
     * Size in bytes necessary to send or receive this object.
     * The size is constant for the livetime of an object but might be 
     * different among different objects of the same type. 
     * <P>
     * For testing purposes only it is possible to change the size of
     * an object. This however requires a certain interplay between the 
     * objects that change their size and the protocol descriptions 
     * of the OV-chip protocol layer.
     *
     * @return size in bytes
     */
    public short size();


    /**
     * Compatibility check for declared and supplied arguments and results.
     * See <a href="#apdu_compatibility">the compatibility 
     * check explanations.</a>
     * Invoked on the declared argument or result of some 
     * {@link Protocol_step} instance with the actual argument or result
     * as argument. Should return true precisely if the actual argument/result
     * is considered binary compatible with the declard one. The
     * method usually checks for type and size.
     * <P>
     * The compatibility check is done in some assertion on the host side.
     * So if this method returns false, usually an assertion fails soon 
     * afterwards.
     * <P>
     * This method need not implement a symmetric relation. For instance
     * {@code some_modulus.is_compatible_with(some_host_modulus)} returns
     * true if {@code some_modulus} and {@code some_host_modulus} have the
     * same size. However, 
     * {@code some_host_modulus.is_compatible_with(some_modulus)} 
     * always returns false, because {@link ds.ov2.bignat.Host_modulus 
     * Host_modulus} objects should never appear in {@link Protocol_step} 
     * instances.
     *
     * @param o actual argument or result
     * @return true if this (the declared argument or result) is considered 
     *         binary compatible with {@code o}.
     */
    public boolean is_compatible_with(Object o);


    /**
     * Serialization of this object.
     * Write at most {@code len} bytes of the state of this 
     * object into the byte array {@code byte_array} starting at
     * index {@code byte_index}. The contents of {@code byte_array} up to 
     * index {@code byte_index -1} must not be modified.
     * {@code this_index} bytes of the state
     * have already been written in preceeding calls to this method.
     * Therefore, the first byte written must be the byte 
     * with index {@code this_index}
     * of the state of this object. If the remaining portion of the state
     * fits into {@code len} bytes the complete state must be serialized.
     * If it does not fit, {@code len} bytes must be written now and the 
     * remainder of the state is serialized in succeeding calls to this
     * method with a suitably adjusted {@code this_index} argument.
     * If {@code this_index} is 0 then serialization starts with this call.
     * <P>
     * {@code len} is at least 1, but otherwise arbitrary. It might 
     * equal the expected size of the serialized state, but it might also 
     * equal the remaining available space in {@code byte_array}. If 
     * {@code len} is greater than the number of bytes needed only the bytes
     * needed for serialization must be written. 
     * <P>
     * In total, precisely {@link #size this.size()} bytes must be written
     * before complete serialization is signalled by the return value.
     * <P>
     * The return value signals wheter serialization completed (or if
     * this method must be called again) and the actual number of bytes
     * written. There are three possible situations, depending on the 
     * size of the remaining portion of the state of this object and 
     * the {@code len} parameter:
     * <DL>
     * <DT>The remaining portion of the state fits into less then {@code len} 
     *     bytes.
     * <DD>The complete remaining state must be written and the return
     *     value is the number of bytes written (which is strictly lesser 
     *     than {@code len}).
     * <DT>The remaining portion of the state is larger than {@code len} bytes.
     * <DD>{@code len} bytes of the remaining portion of the state must be 
     *     written. The return value is the number of bytes written, 
     *     that is, {@code len} is returned.
     * <DT>The remaining portion of the state fits into precisely {@code len}
     *     bytes.
     * <DD>The remaining portion of the state must be serialized completely 
     *     by writing {@code len} bytes. <STRONG>The return 
     *     value is {@code len + 1}.</STRONG>
     * </DL>
     *
     * @param len available space in {@code byte_array}, at most {@code len}
     *         bytes should be written into {@code byte_array}
     * @param this_index greater than or equal to zero, at most 
     *         {@code this.size() -1}, number of bytes that
     *         have already been written in preceeding calls. Serialization
     *         must continue at the byte with index {@code this_index}.
     * @param byte_array data array to serialize the state into
     * @param byte_index index in {@code byte_array} where the first byte must
     *         be written
     * @return the number of bytes actually written, except for the case 
     *          where serialization finished by writing precisely 
     *          {@code len} bytes, in this case {@code len + 1} is 
     *          returned.
     *          <P>
     *          Equivalently, {@code len} is returned if serialization must 
     *          continue after writing {@code len} bytes. Some 
     *          {@code x < len} is returned if serialization finished by writing
     *          {@code x} bytes. {@code len + 1} is returned if serialization
     *          finished by writing {@code len} bytes.
     */
    public short to_byte_array(short len, short this_index, 
                              byte[] byte_array, short byte_index);


    /**
     * Deserialization of this object.
     * Read at most {@code len} bytes of the state of this 
     * object from the byte array {@code byte_array} starting at
     * index {@code byte_index}. The byte array {@code byte_array} 
     * must not be modified.
     * {@code this_index} bytes of the state
     * have already been read in preceeding calls to this method.
     * Therefore, the first byte read must be the byte with 
     * index {@code this_index}
     * of the state of this object. 
     * If the remaining unitialized portion of the state of this object 
     * requires more than {@code len} bytes then {@code len} bytes 
     * of the state must be read now and deserialization will continues 
     * in succeeding calls to this method 
     * with a suitably adjusted {@code this_index} argument.
     * If {@code this_index} is 0 then deserialization starts with this call.
     * <P>
     * {@code len} is at least 1, but otherwise arbitrary. It might 
     * be equal to {@code byte_array.length - byte_index} but it could be 
     * less.
     * <P>
     * In total, precisely {@link #size this.size()} bytes must be read
     * before complete deserialization is signalled by the return value.
     * <P>
     * The return value signals wheter deserialization completed (or if
     * this method must be called again) and the actual number of bytes
     * read from {@code byte_array}. 
     * There are three possible situations, depending on the 
     * size of the remaining uninitialized portion
     * of the state of this object and 
     * the {@code len} parameter:
     * <DL>
     * <DT>The remaining uninitialized portion requires less then {@code len} 
     *     bytes.
     * <DD>Deserialization is completed by reading the required number of 
     *     bytes. The return 
     *     value is the number of bytes read (which is strictly lesser 
     *     than {@code len}).
     * <DT>The remaining uninitialized portion of the state requires more than 
     *     {@code len} bytes.
     * <DD>{@code len} bytes must be read now and deserialization continues 
     *     in the following call to this function.
     *     The return value is the number of bytes read, 
     *     that is, {@code len} is returned.
     * <DT>The remaining uninitialized portion of the state requires
     *     precisely {@code len} bytes.
     * <DD>Deserialization is finished by reading {@code len} bytes.
     *     <STRONG>The return 
     *     value is {@code len + 1}.</STRONG>
     * </DL>
     *
     * @param len number of available bytes in {@code byte_array}
     *          starting at index {@code byte_index}, at most {@code len}
     *          bytes should be read.
     * @param this_index greater than or equal to zero, at most 
     *          {@code this.size() -1}, number of bytes that
     *          have already been read in preceeding calls. Deserialization
     *          must continue at the byte with index {@code this_index}.
     * @param byte_array data array to deserialize the state from
     * @param byte_index index in {@code byte_array} of the first available
     *         data byte
     * @return the number of bytes read, except for the case 
     *           where deserialization finished by reading precisely 
     *           {@code len} bytes, in this case {@code len + 1} is 
     *           returned.
     *           <P>
     *           Equivalently, {@code len} is returned if deserialization must 
     *           continue after reading {@code len} bytes. Some 
     *           {@code x < len} is returned if deserialization 
     *           finished by reading
     *           {@code x} bytes. {@code len + 1} is returned if 
     *           deserialization
     *           finished by reading {@code len} bytes.
     */
    public short from_byte_array(short len, short this_index,
                                 byte[] byte_array, short byte_index);
}

